/*
 * jQuery Slideshow Plug-in
 *
 * Author: Chan Chun Yin
 * Date: 2011-04-14
 *
 * Version:	1.0.1
 * Updated at 2012-07-23
 *
 * History:
 *	1.0.1	added vertical scroll direction.
 *
 * Remarks:
 *	Functions scroll and slideTo could be combined into single function
 *
 * Usage:
 *	Initial:
 *		$("div#slideshowContainer").slideshow({"direction": "rtl", "autoStart":false, "autoSlide":false});
 *		(options please refer to the $.Slideshow.defaults at the bottom of this script.)
 *
 * 	Functions:
 *		Show the previous slides
 *	 	$("div#slideshowContainer").slideshow("previous");
 *
 *		Show the next slides
 *		$("div#slideshowContainer").slideshow("next");
 *
 *		Slide-to specified slides (start from 1)
 *		$("div#slideshowContainer").slideshow("slideTo", "1");
 *
 */
(function($){

	$.fn.slideshow = function (options) {
		var method = typeof arguments[0] == "string" && arguments[0];
		var args = method && Array.prototype.slice.call(arguments, 1) || arguments;
		// get a reference to the first slideshow found
		var self = (this.length == 0) ? null : $.data(this[0], "slideshow");

		// if a method is supplied, execute it for non-empty results
		if( self && method && this.length ){

			// if request a copy of the object, return it
			if( method.toLowerCase() == "object" ) return self;
			// if method is defined, run it and return either it's results or the chain
			else if( self[method] ){
				// define a result variable to return to the jQuery chain
				var result;
				this.each(function (i){
					// apply the method to the current element
					var r = $.data(this, "slideshow")[method].apply(self, args);

					// if first iteration we need to check if we're done processing or need to add it to the jquery chain
					if( i == 0 && r ){
						// if this is a jQuery item, we need to store them in a collection
						if( !!r.jquery ){
							result = $([]).add(r);
						// otherwise, just store the result and stop executing
						} else {
							result = r;
							// since we're a non-jQuery item, just cancel processing further items
							return false;
						}
					// keep adding jQuery objects to the results
					} else if( !!r && !!r.jquery ){
						result = result.add(r);
					}
				});
				// return either the results (which could be a jQuery object) or the original chain
				return (result == undefined) ? this : eval(result);
			// everything else, return the chain
			} else {
				return this;
			}
		// initializing request
		} else {
			// create a new slideshow for each object found
			return this.each(function (){
				new $.slideshow(this, options);
			});
		};
	}

	$.slideshow = function (slideshow, options){
		options = $.extend({}, $.slideshow.defaults, options);

		var self = this;
		var $slideshow = $(slideshow);
		var $divs = $slideshow.find("> ol, > div");
		var t = 0;
		var current = options.defaultSlide | 0;
		var hard_paused = false;
		var isSliding = false;
		var paused = false;
		var loop_count = 0;
		var direction = options.direction;
		var endPos;

		// store a reference to this slideshow
		$.data($slideshow[0], "slideshow", self);

		// the scrolling items end scroll position
		var endParams = {};

		// the scrolling items init position
		var params = {};

		if (direction == "rtl" || direction == "ltr") {
			endParams = {left: "-99999px", display: "none"};
			params = {left: (direction == "rtl" ? "+" : "-") + ($slideshow.innerWidth()) + "px", display: "inline"};
		} else {
			endParams = {top: "-99999px", display: "none"};
			params = {top: (direction == "btt" ? "+" : "-") + ($slideshow.innerHeight()) + "px", display: "inline"};
		}

		this.getCurrentslide = function (){
			return current.toString();
		}

		this.isSilding = function (){
			return isSliding.toString();
		}

		// pause the slideshow
		this.pause = function (){
			// mark as hard pause (no resume on hover)
			hard_paused = true;
			// pause scrolling
			pause();
		}

		// resume the slideshow
		this.resume = function (){
			// mark as hard pause (no resume on hover)
			hard_paused = false;
			// resume scrolling
			resume();
		}

		// show next slide
		this.next = function (delay, callback){
			if (isSliding) return;

			if ( delay == null ) delay = 0;		// get the delay time

			if (t > 0) {
				resetTimer();
			} else if (paused) {
				paused = false;
			}

			if (options.direction == "rtl" || options.direction == "ltr")
				direction = (options.direction == "rtl") ? "rtl" : "ltr";
			else
				direction = (options.direction == "btt") ? "btt" : "ttb";

			scroll(delay, callback);
		}

		// show previous slide
		this.previous = function (delay, callback){
			if (isSliding) return;

			if ( delay == null ) delay = 0;		// get the delay time

			if (t > 0) {
				resetTimer();
			} else if (paused) {
				paused = false;
			}

			if (options.direction == "rtl" || options.direction == "ltr")
				direction = (options.direction == "rtl") ? "ltr" : "rtl";
			else
				direction = (options.direction == "btt") ? "ttb" : "btt";

			slideTo(current, delay, callback);
		}

		// go to target slide
		this.slideTo = function (index, delay, callback){
			if (isSliding) return;

			if ( delay == null ) delay = 0;		// get the delay time

			if ( (index-1 != current) && (t > 0) ) {
				resetTimer();
			} else if (paused) {
				paused = false;
			}

			if (options.direction == "rtl" || options.direction == "ltr")
				direction = (current > index-1) ? ((options.direction == "rtl") ? "ltr" : "rtl") : direction;
			else
				direction = (current > index-1) ? ((options.direction == "btt") ? "ttb" : "btt") : direction;

			slideTo(index, delay, callback);
		}

		function resetTimer() {
			clearTimeout(t);
			t = 0;
		}

		function initNavBtn() {
			if (options.useDefaultNav) {
				var sHtml = '';
				//var sHtml = '<center><a href="javascript:;" onclick="$(\'#'+$slideshow.attr('id')+'\').slideshow(\'previous\');"><img src="images/prev.gif" border="0" /></a>';

				for (i=0; i<$divs.length; i++) {
					sHtml += '<a href="javascript:;" onclick="$(\'#'+$slideshow.attr('id')+'\').slideshow(\'slideTo\', '+(i+1)+');"><img id="'+options.navbtnIDPrefix+(i+1)+'" src="/images/dot'+(i == current ? '_on' : '')+'.png" border="0" /></a>';
				}

				//sHtml += '<a href="javascript:;" onclick="$(\'#'+$slideshow.attr('id')+'\').slideshow(\'next\');"><img src="images/next.gif" border="0" /></a></center>';

				$slideshow.find("~ #navButtons").html(sHtml);
			}
		}

		function initPosition() {
			updatePosition ();
			$divs.css(params);

			if (direction == "rtl" || direction == "ltr") {
				$divs.eq(current).css("left", 0);
			} else {
				$divs.eq(current).css("top", 0);
			}
		}

		function updatePosition () {
			if (direction == "rtl" || direction == "ltr") {
				params = {left: (direction == "rtl" ? "+" : "-") + ($slideshow.innerWidth()) + "px", display: "inline"};
			} else {
				params = {top: (direction == "btt" ? "+" : "-") + ($slideshow.innerHeight()) + "px", display: "inline"};
			}
		}

		function updateNav(index) {
			if (options.useDefaultNav) {
				$("img[id^='"+options.navbtnIDPrefix+"']").attr("src", "/images/dot.png");
				$("img[id='"+options.navbtnIDPrefix+(index+1)+"']").attr("src", "/images/dot_on.png");
			}
		}

		function scroll(delay, callback) {
			// if paused, stop processing
			if ( paused ) return false;

			if ( !options.cycle && current+1 == $divs.length) return false;

			if ( delay == null ) delay = options.pauseTime;		// get the delay time

			var $div = $divs.eq(current);						// get the item which needed to scroll
			var $divNext = $divs.eq((current+1)%$divs.length);	// get the next item which needed to scroll

			t = setTimeout(function () {
				if ( paused ) return false;
				resetTimer();
				isSliding = true;
				initPosition();
				updateNav((current+1)%$divs.length);

				if (options.direction == "rtl" || options.direction == "ltr") {
					// get the end position
					endPos = (isNaN($div.outerWidth())?$div.innerWidth():$div.outerWidth()) * ((direction == "rtl") ? -1 : 1);

					$divNext.css({"left": ((direction == "rtl") ? "" : "-") + ($slideshow.innerWidth()) + "px"});

					$div.animate({left: endPos + "px"}, options.scrollSpeed, "swing", function (){finish();});
					$divNext.animate({left: 0}, options.scrollSpeed, "swing");
				} else {
					// get the end position
					endPos = (isNaN($div.outerHeight())?$div.innerHeight():$div.outerHeight()) * ((direction == "btt") ? -1 : 1);

					$divNext.css({"top": ((direction == "btt") ? "" : "-") + ($slideshow.innerHeight()) + "px"});

					$div.animate({top: endPos + "px"}, options.scrollSpeed, "swing", function (){
						finish();
						if (typeof callback == 'function') callback();
					});
					$divNext.animate({top: 0}, options.scrollSpeed, "swing");
				}
			}, delay);
		}

		function slideTo(index, delay, callback) {
			if ( !options.cycle && index-1 == -1) return false;

			if ( delay == null ) delay = 0;		// get the delay time

			index = index-1>-1?((index-1)%$divs.length):$divs.length-1;

			var $div = $divs.eq(current);			// get the item which needed to scroll
			var $divTarget = $divs.eq(index);		// get the item which needed to scroll

			t = setTimeout(function () {
				if ( paused ) return false;
				resetTimer();
				isSliding = true;
				initPosition();
				updateNav(index);

				if (options.direction == "rtl" || options.direction == "ltr") {
					// get the end position
					endPos = (isNaN($div.outerWidth())?$div.innerWidth():$div.outerWidth()) * ((direction == "rtl") ? -1 : 1);

					$divTarget.css({"left": ((direction == "rtl") ? "" : "-") + ($slideshow.innerWidth()) + "px"});

					$div.animate({left: endPos + "px"}, options.scrollSpeed, "swing", function (){finish(index);});
					$divTarget.animate({left: 0}, options.scrollSpeed, "swing");
				} else {
					// get the end position
					endPos = (isNaN($div.outerHeight())?$div.innerHeight():$div.outerHeight()) * ((direction == "btt") ? -1 : 1);

					$divTarget.css({"top": ((direction == "btt") ? "" : "-") + ($slideshow.innerHeight()) + "px"});

					$div.animate({top: endPos + "px"}, options.scrollSpeed, "swing", function (){
						finish(index);
						if (typeof callback == 'function') callback();
					});
					$divTarget.animate({top: 0}, options.scrollSpeed, "swing");
				}
			}, delay);
		}

		function finish(index){
			isSliding = false;
			if (index != undefined) current = index-1;
			paused = (!options.autoSlide);

			$divs.css(endParams);

			next();
		}

		function pause() {
			// mark the message as paused
			paused = true;
			resetTimer();
		}

		function resume() {
			// mark the message as resumed
			paused = false;
			scroll();
		}

		function previous() {
			if (options.direction == "rtl" || options.direction == "ltr")
				direction = (options.direction == "rtl") ? "ltr" : "rtl";
			else
				direction = (options.direction == "btt") ? "ttb" : "btt";

			current = current-1>-1?((current-1)%$divs.length):$divs.length-1;
			scroll();
		}

		function next() {
			current = (current+1) % $divs.length;

			if (options.direction == "rtl" || options.direction == "ltr") {
				direction = (options.direction == "rtl") ? "rtl" : "ltr";
				$divs.eq(current).css({"left": 0, display: "inline"});
			} else {
				direction = (options.direction == "btt") ? "btt" : "ttb";
				$divs.eq(current).css({"top": 0, display: "inline"});
			}

			scroll();
		}

		if( options.pauseOnHover ){
			$slideshow.hover(
				function (){
					// if hard paused, prevent hover events
					if ( hard_paused ) return false;
					// pause scrolling
					pause();
				}
				, function (){
					// if hard paused, prevent hover events
					if ( hard_paused ) return false;
					// resume scrolling
					resume();
				}
			);
		}

		initNavBtn();

		$divs.css(endParams);

		if (direction == "rtl" || direction == "ltr") {
			$divs.eq(current).css({"left": 0, display: "inline"});
		} else {
			$divs.eq(current).css({"top": 0, display: "inline"});
		}

		if (!options.autoStart) {
			paused = true;
		}
		scroll();
		//slideTo(current, options.pauseTime);
	};

	$.slideshow.destory = function (){

	}

	$.slideshow.defaults = {
		direction: "rtl", 						// the direction of the slideshow scroll (can be "right to left" (rtl); "left to right" (ltr); "bottom to top" (btt); "top to bottom" (ttb))
		scrollSpeed: 1000, 						// the speed of the scrolling (must > 1) (smaller number is faster)
		pauseTime: 4000, 						// the time to wait before showing the next message (in millionseconds)
		loop: -1, 								// determine how many times to loop through the slideshows (-1 = infinite)
		autoStart: true, 						// the slideshow to be shown or not when the page is loaded
		autoSlide: true, 						// auto slideshow played
		cycle:	true,							// play the first slides after the last slides
		pauseOnHover: false, 					// determine if we should pause on mouse over
		useDefaultNav: false, 					// has the navigation buttons
		navbtnIDPrefix: "btn_",					// navigation buttons id prefix (e.g. id="navbtn_1", "navbtn_" is the prefix)
		defaultSlide: 0
	};

})(jQuery);